from datetime import datetime

import os


# 全局数据变量
CDTDLG_DIR = r""
ACTVHH_DIR = r""

# cdtdlg 数据缓存区
CDTDLG = []
# 宽表保存记录缓存区
WIDE_RECORDWES = []
# 确定记录结束符
RECORD_TAIL = '^ENDROW'
#构建 CDTDLG 账号索引
CDTDLG_INDEX = {}

# 货币字典
CurrencyDictionary={
    '000':"CNY",
    '001':"CNY",
    '011':'CNY',
    '002':'AUA',
    '003':'AUB',
    '010':'BDT',
    '012':'GBP',
    '013':'HKD',
    '014':'USD',
    '015':'CHF',
    '016':'DEM',
    '017':'FRF',
    '018':'SGD',
    '019':'PKR',
    '020':'NLG',
    '021':'SEK',
    '022':'DKK',
    '023':'NOK',
    '027':'JPY',
    '028':'CAD',
    '029':'AUD',
    '030':'TZS',
    '031':'ESP',
    '032':'MYR',
    '033':'XEU',
    '034':'XAU',
    '035':'GLD',
    '036':'XAG',
    '037':'XDR',
    '038':'EUR',
    '040':'LKR',
    '041':'DZD',
    '042':'FIM',
    '044':'IQD',
    '046':'MAD',
    '047':'SLL',
    '048':'IRR',
    '049':'NPR',
    '060':'CNY',
    '061':'ALL',
    '063':'KPW',
    '064':'VND',
    '066':'BGL',
    '070':'ZAR',
    '071':'LYD',
    '080':'ZMK',
    '081':'MOP',
    '082':'PHP',
    '084':'THB',
    '085':'INR',
    '087':'NZD',
    '088':'KRM',
    '089':'SYP',
    '094':'USD',
    '095':'CHF',
    '240':'ROL',
    '601':'GHC'
}

bank_map={'2465': '中国银行黑龙江省分行',
 '2021': '中国银行吉林省分行汽车厂支行',
 '2118': '中国银行吉林省分行上海路支行',
 '2289': '中国银行吉林省分行西安大路支行',
 '2023': '中国银行吉林省分行开发区支行', '2024': '中国银行吉林省分行建设街支行',
 '2129': '中国银行吉林省分行工农大路支行', '2128': '中国银行吉林省分行大经路支行',
 '2295': '中国银行吉林省分行吉林大路支行', '2120': '中国银行吉林省分行朝阳支行',
 '2294': '中国银行吉林省分行榆树支行', '2015': '中国银行吉林省分行九台支行',
 '2019': '中国银行吉林省分行德惠支行', '2214': '中国银行吉林市分行',
 '2288': '中国银行吉林船营支行', '2287': '中国银行吉林龙潭支行', '2028': '中国银行吉林昌邑支行',
 '2296': '中国银行吉林市分行蛟河支行', '2202': '中国银行延边州分行',
 '2286': '中国银行延边州分行敦化支行', '2009': '中国银行延边州分行安图支行',
 '2016': '中国银行延边州分行珲春支行', '2012': '中国银行延边州分行图门支行',
 '2010': '中国银行延边州分行龙井支行', '2104': '中国银行四平市分行',
 '2109': '中国银行四平市分行英城支行', '2108': '中国银行四平市分行铁东支行',
 '2290': '中国银行四平市分行公主岭支行', '2161': '中国银行通化市分行',
 '2292': '中国银行通化市分行梅河口支行', '2291': '中国银行通化市分行集安支行',
 '2011': '中国银行通化市分行辉南支行', '2201': '中国银行白城市分行',
 '2014': '中国银行白城市分行大安支行', '2160': '中国银行辽源市分行',
 '2027': '中国银行东吉支行', '2298': '中国银行辽源市分行桥西支行',
 '2299': '中国银行辽源市分行东丰支行', '2284': '中国银行松原市分行',
 '2022': '中国银行松原市分行油田支行', '2020': '中国银行松原市分行宁江支行',
 '2285': '中国银行白山市分行', '2293': '中国银行白山市分行抚松支行',
 '2112': '中国银行吉林省分行新民大街支行', '2208': '中国银行吉林省分行',
 '2545': '中国银行佳木斯市顺和支行', '2540': '中国银行佳木斯市保卫支行',
 '2541': '中国银行佳木斯市建设支行',
 '2326': '中国银行黑河市开发区支行', '2310': '中国银行绥化市西城区支行',
 '2311': '中国银行鹤岗市站前支行', '2321': '中国银行双鸭山市四马路支行',
 '2312': '中国银行大兴安岭地区加格达奇支行', '2316': '中国银行七台河市新兴支行',
 '2303': '中国银行伊春市南岔支行', '2502': '中国银行齐齐哈尔市分行',
 '2501': '中国银行牡丹江市分行', '2503': '中国银行佳木斯市分行',
 '2530': '中国银行大庆市分行', '2516': '中国银行黑河市分行',
 '2519': '中国银行绥化市分行', '2518': '中国银行鸡西市分行',
 '2515': '中国银行鹤岗市支行', '2520': '中国银行双鸭山市分行',
 '2544': '中国银行大兴安岭地区分行', '2521': '中国银行七台河市分行',
 '2513': '中国银行双城支行', '2534': '中国银行尚志支行',
 '2546': '中行五常支行', '2319': '中国银行巴彦支行', '2341': '中国银行哈尔滨市霁虹支行',
 '2542': '中国银行克山支行', '2535': '中国银行依安支行', '2307': '中国银行龙江支行',
 '2552': '中国银行讷河支行', '2522': '中国银行绥芬河支行',
 '2300': '中国银行海林支行', '2309': '中国银行穆棱支行',
 '2538': '中国银行宁安支行', '2550': '中国银行东宁支行',
 '2548': '中国银行富锦支行', '2523': '中国银行同江支行',
 '2511': '中国银行阿城支行', '2554': '中国银行呼兰支行',
 '2517': '中国银行北安支行', '2302': '中国银行嫩江支行',
 '2557': '中国银行海伦支行', '2527': '中国银行安达支行',
 '2539': '中国银行肇东支行', '2525': '中国银行密山支行',
 '2524': '中国银行虎林支行', '2543': '中国银行勃利支行',
 '2514': '中国银行伊春市分行',
 '2510': '中国银行哈尔滨市兆麟支行',
 '2547': '中国银行哈尔滨市南岗支行',
 '2512': '中行道里支行', '2526': '中国银行哈尔滨市道外支行',
 '2332': '中国银行哈尔滨市动力支行', '2322': '中国银行哈尔滨市开发区支行',
 '2334': '中国银行哈尔滨市平房支行', '2301': '中国银行大庆市开发区支行',
 '2533': '中国银行大庆市卧里屯支行', '2323': '中国银行大庆市红岗支行', '2531': '中国银行大庆市高台子支行', '2330': '中国银行大庆市朝阳沟支行', '2529': '中国银行大庆市林源支行', '2532': '中国银行大庆市创业庄支行', '2555': '中国银行大庆市东风路支行', '2345': '中国银行大庆油田支行', '2528': '中国银行齐齐哈尔市富拉尔基支行', '2320': '中国银行齐齐哈尔市永兴支行', '2537': '中国银行牡丹江市裕民支行', '2553': '中国银行牡丹江市光华支行', '1405': '内蒙分行', '1594': '新华支行', '1314': '新城支行', '1598': '中国银行内蒙分行车站支行', '1307': '中国银行内蒙分行中山支行', '1599': '中国银行内蒙分行玉泉支行', '1316': '中国银行内蒙分行八拜支行',
 '1581': '中国银行赤峰分行', '1310': '中国银行元宝山支行', '1305': '中国银行宁城支行',
 '1311': '中国银行巴林左旗支行',
 '1582': '中国银行集宁分行', '1301': '中国银行丰镇支行', '1583': '中国银行包头分行',
 '1595': '中国银行东河支行',
 '1596': '中国银行青山支行', '1317': '中国银行昆区支行',
 '1318': '中国银行九原支行', '1584': '中国银行海拉尔分行',
 '1586': '中国银行通辽分行', '1587': '中国银行鄂尔多斯分行', '1309': '中国银行达拉特支行', '1588': '中国银行乌兰浩特分行', '1589': '中国银行二连浩特分行', '1590': '中国银行乌海分行', '1315': '中国银行乌达支行', '1591': '中国银行巴彦浩特分行', '1306': '中国银行吉兰泰分理处', '1592': '中国银行临河分行', '1308': '中国银行乌拉特前旗支行', '1593': '中国银行锡林浩特分行', '1585': '中国银行满洲里分行', '1041': '中国银行山西省分行', '1049': '中国银行太原市鼓楼支行',
 '1075': '中国银行太原市漪汾支行', '1134': '中国银行太原市平阳支行', '1073': '中国银行太原市并州支行', '1099': '中国银行太原市滨河支行', '1022': '中国银行太原市古交支行', '1013': '中国银行太原市清徐支行', '1169': '中国银行大同市分行', '1009': '中国银行大同市分行左云支行', '1017': '中国银行大同市分行矿务局支行', '1167': '中国银行朔州市分行', '1088': '中国银行朔州市平朔支行', '1042': '中国银行朔州市朔城区支行', '1298': '中国银行朔州市平鲁区支行', '1008': '中国银行山阴县支行', '1016': '中国银行朔州市怀仁县支行', '1299': '中国银行朔州市应县支行', '1284': '中国银行忻州分行', '1289': '中国银行原平市支行', '1294': '中国银行五台县支行', '1006': '中国银行定襄县支行', '1285': '中国银行晋中市分行', '1068': '中国银行晋中市分行灵石办事处', '1059': '晋中市分行介休支行',
 '1290': '中国银行晋中市分行太谷支行',
 '1021': '中国银行晋中市分行祁县支行', '1095': '中国银行晋中市分行榆社支行',
 '1283': '中国银行运城分行', '1043': '中国银行闻喜县支行',
 '1011': '中国银行永济市支行', '1054': '中国银行河津市支行',
 '1069': '河津支行禹门支行', '1282': '中国银行临汾分行',
 '1291': '中国银行侯马市支行', '1057': '中国银行洪洞县支行',
 '1024': '中国银行霍州市支行', '1286': '中国银行阳泉市分行',
 '1293': '中国银行平定县支行', '1044': '中国银行盂县支行',
 '1287': '中国银行晋城市分行', '1048': '中国银行阳城县支行',
 '1055': '中国银行高平市支行', '1023': '中国银行沁水县支行',
 '1288': '中国银行离石分行', '1047': '中国银行交城县支行',
 '1015': '中国银行汾阳县支行', '1010': '中国银行孝义市支行',
 '1281': '中国银行长治市分行', '1012': '中国银行长治市分行潞城市支行',
 '1058': '中国银行长治市分行沁县支行', '1046': '中国银行长治市分行黎城县支行',
 '1025': '中国银行长治市分行襄垣县支行', '1096': '中国银行长治市分行长治县分理处',
 '2111': '中国银行吉林丰满支行'}


Dictionary_Provinces = {
    '00009':'黑龙江省',
    '00008':'吉林省',
    '00006':'内蒙古自治区',
    '00005':'山西省'
}



"""============================================================================"""
# 初始化CDTDLG
def init_data():
    global CDTDLG
    # 读取 CDTDLG 文件
    for filename in os.listdir(CDTDLG_DIR):
        file_path = os.path.join(CDTDLG_DIR, filename)
        # 跳过子目录，只处理文件
        if not os.path.isfile(file_path):
            continue
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                for line in f:
                    # 检查行是否以 "^row" 结尾（自动忽略行尾换行符）
                    if line.rstrip('\n\r').endswith(RECORD_TAIL):
                        # 去除换行符后按 '|' 分割
                        fields = line.rstrip('\n\r').split('|')
                        CDTDLG.append(fields)
        except Exception as e:
            print(f"⚠️ 跳过文件 {filename}（无法读取）: {e}")
    print(f'✅ 共加载 {len(CDTDLG)} 条以 "{RECORD_TAIL}" 结尾的有效记录')
    # 构建CDTDLG 账号查找字典
    build_cdtdlg_index(10)
    print(f'成功构建CDTDLG账号查找字典')
    return

# 预处理：构建账号 -> 记录列表 的映射（一次性）
""" 构建 CDTDLG 账号索引：以 record[account_index] 为键，
       值为该记录在全局列表 CDTDLG 中的下标（索引）列表。
       例如：CDTDLG_INDEX['123456'] = [0, 3, 7]
       表示账号 '123456' 出现在 CDTDLG 的第 0、3、7 条记录中。
"""
def build_cdtdlg_index(account_index: int = 0):
    global CDTDLG_INDEX
    CDTDLG_INDEX = {}
    for idx, record in enumerate(CDTDLG):
        if len(record) > account_index:
            acc = record[account_index]
            if acc not in CDTDLG_INDEX:
                CDTDLG_INDEX[acc] = []
            CDTDLG_INDEX[acc].append(idx)  # 保存下标，而非 record 本身


def find_cdtdlg_by_account(account: str):
    """
    根据账号查找 CDTDLG 中的第一条匹配记录（通过索引间接获取）
    返回：字段列表（list） 或 None（未找到）
    """
    indices = CDTDLG_INDEX.get(account)
    if indices and len(indices) > 0:
        return CDTDLG[indices[0]]  # 返回第一条记录
    return None


# 交付数据加工格式

# 数据分隔符
DELIMITER = '|'
# 数据量大小
MAX_SIZE = 500 * 1024 * 1024  # 500MB（先别用5GB！）
# 交付数据名称
WIDE_NAME = ""

# -------------- 1. 尾部 JSON 模板 --------------
TAIL_JSON_TEMPLATE = {
    "TabName"        : "dep_trade_pro",
    "AssemblyID"     : "NEW_JL00_P6",
    "PlatformID"     : "P6",
    "IsSplitFlag"    : "0",
    "MechanismID"    : "000008",
    "DataStartDate"  : "20251010",
    "DataEndDate"    : "20251010",
    "IncID"          : "0",
    # 真实条数等关闭前再填
    "RecNum"         : "{rec_num}",
    "Sep"            : DELIMITER,
    "CycFlag"        : "D",
    "TableGenType"   : "0",
    "GenTime"        : "{gen_time}"
}

# 对公数据加工 ACTVHH

def read_actvhh_records(root_dir, record_tail=RECORD_TAIL):
    """
    生成器：逐行读取 root_dir 下所有文件，yield 以 record_tail 结尾的有效记录（字段列表）
    参数:
        root_dir (str): 数据文件目录路径
        record_tail (str): 有效行结尾标记，默认 '^row'
    产出:
        List[str]: 每条有效记录的字段列表（已 split('|')）
    """
    for filename in os.listdir(root_dir):
        file_path = os.path.join(root_dir, filename)
        # 跳过子目录
        if not os.path.isfile(file_path):
            continue
        print(f"正在处理文件: {filename}")
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore', buffering=1024 * 1024) as f:
                for line in f:
                    # 去除行尾换行符后判断结尾
                    stripped_line = line.rstrip('\n\r')
                    if stripped_line.endswith(record_tail):
                        # 分割字段并 yield
                        yield stripped_line.split('|')
        except Exception as e:
            print(f"⚠️ 跳过文件 {filename}（读取错误）: {e}")

# 对公数据加工 ACTVHH
def processing_ACTVHH():
    deployment_time = datetime.now().strftime('%Y%m%d%H%M%S')  # ✅ 统一投产时间
    output_file = None
    file_index = 1
    current_size = 0
    for actvhh in read_actvhh_records(ACTVHH_DIR):
        # 宽表记录 在这里做宽表映射、写文件、入库等
        wide_line = [""] * 140
        # 数据解析
        # 1 客户号 在ACTVHH表中第8个字段  CUSIDT
        wide_line[0] = '000000000'
        if actvhh[8] :
            wide_line[0] = actvhh[8]
        # 2 账号 使用ACTVHH表中ORGID3(7),CUSIDT(8),APCODE(9),CURCDE(10) 这四个字段拼接而成
        wide_line[1] = actvhh[7] + actvhh[8] + actvhh[9] + actvhh[10]
        account = wide_line[1]
        # 3 旧帐号 存取2 中的内容
        wide_line[2] = account
        # 4 账号类型
        wide_line[3] = "01"
        # 5 查询卡号
        wide_line[4] = '00000'
        # 6 卡类型
        wide_line[5] = '99'
        # 7 机构号  orgidt
        wide_line[6] = actvhh[1]
        # 8 交易类型
        # 9 借贷标记  txnamt
        if int(actvhh[11]) <= 0:
            wide_line[8] = 'D'
        else:
            wide_line[8] = 'C'
        # 10 币种 curcde
        wide_line[9] = CurrencyDictionary.get(actvhh[10],'XXX')
        # 11 交易金额
        wide_line[10] = f"{round(float(actvhh(11)), 2):.2f}"
        # 12 交易余额
        wide_line[11] = f"{round(float(actvhh(12)), 2):.2f}"
        # 设计个宽表大小5G输出文件，生成最终项目文件
        # 13 交易时间
        vchdat = actvhh[28]  # 日期串  yyyy-mm-dd
        vchtim = actvhh[29]  # 时间串  hh:mi:ss 或 BATCH/None
        # 1. 日期统一转成 yyyyMMdd
        date_part = datetime.strptime(vchdat, "%Y-%m-%d").strftime("%Y%m%d")
        # 2. 时间部分处理
        if vchtim is None or vchtim.upper() == 'BATCH':
            time_part = '000000'
        else:
            time_part = vchtim.replace(':', '')  # hh:mi:ss -> hhmiss
        # 3. 拼接
        wide_line[12] = date_part + time_part  # yyyyMMddhhmiss
        # 22 交易摘要 furinf
        wide_line[21] = actvhh[15]
        # 23 -- 交易网点名称-二级-尽可能恢复 txnbank ==  actorg
        wide_line[22] = bank_map.get(actvhh[23],'')
        # 24 -- 日志号-二级-尽可能恢复 VCHSET
        wide_line[23] = actvhh[3]
        # 35 -- 交易柜员号-二级-尽可能恢复 TLRNUM
        wide_line[34] = actvhh[2]
        # 37 -- 本方账号-二级-尽可能恢复vhh.orgid3,vhh.cusidt,vhh.apcode,vhh.curcde
        wide_line[36] = actvhh[7]+actvhh[8]+actvhh[9]+actvhh[10]
        # 46 -- 定存起始日期-三级-可为空 valdat
        val = actvhh[13]
        if val is None or (isinstance(val, str) and val.strip().upper() == 'NULL') or val == '':
            wide_line[45] = ""  # 或 ''，根据你的需求
        else:
            try:
                # 尝试解析日期时间字符串
                dt = datetime.strptime(val.strip(), '%Y-%m-%d %H:%M:%S')
                wide_line[45] = dt.strftime('%Y-%m-%d')  # 转为 'YYYY-MM-DD'
            except (ValueError, AttributeError, TypeError):
                # 如果格式不对或不是字符串，保留原样或设为 None
                wide_line[45] = ""
        # 86 -- 输入当天套顺序号 vchset
        wide_line[85] = actvhh[3]
        # 87 -- 输入当天套内顺序号 setseq
        wide_line[86] = actvhh[4]
        # 88 -- 记帐日 erydat
        wide_line[87] = actvhh[5]
        # 90 -- 建卡销卡凭证编号 regnum
        wide_line[49] = actvhh[22]
        # 91-- 传票输入方式 erytyp
        wide_line[90] = actvhh[27]
        # 117 交易本方核算码 apcode
        wide_line[116] = actvhh[9]
        # 118 -- 交易本方货币码-三级-可为空  curcde
        wide_line[117] = CurrencyDictionary.get(actvhh[10],'XXX')
        # 127 --源入湖物理文件名
        wide_line[126] = 'ACTVHH'
        # 128 --源入湖表名
        wide_line[127] = 'ACTVHH'
        # 129 --源系统
        wide_line[118] = 'SBS/SBSP'
        # 130 --源归属地编码
        wide_line[119] = actvhh[14]
        # 131 --源归属地

        # 132 --源时间节点
        wide_line[131] = '20100615'
        # 133 --数据来源
        wide_line[132] = 'ODMS'
        # 134 -- 交易记录属性-一级-必须恢复：（对公“01”，对私“02”）
        wide_line[133] = '01'
        # 138 跨行标识
        wide_line[137] = '2'
        # 139 -- 交易动账标识-一级-必须恢复 TXNAMT
        if int(actvhh[15]) == 0:
            wide_line[138] = '0'
        else:
            wide_line[138] = '1'
        # 140 系统时间
        # wide_line[139] = datetime.now().strftime('%Y%m%d%H%M%S')
        wide_line[139] = '20251031'



        """========================================================================="""
        # 1 每一条wide_line 目前是列表 要转为每个字段以“|”分隔的字符串最后也要添加
        # 2 添加wide_line 到WIDE_RECORDERS 中
        # 3 判断WIDE_RECORDERS 大小达到5G 输出文件，清空WIDE_RECORDRS
        # --- 写入文件（流式，不缓存）---
        line_str = DELIMITER.join(str(x) if x is not None else '' for x in wide_line) + '\n'
        line_bytes = line_str.encode('utf-8')
        # 检查是否需要新建文件
        if output_file is None or current_size + len(line_bytes) > MAX_SIZE:
            if output_file:
                output_file.close()
            filename = f"{WIDE_NAME}{file_index:03d}.txt"
            print(f"📁 创建新文件: {filename}")
            output_file = open(filename, 'wb')
            file_index += 1
            current_size = 0
        output_file.write(line_bytes)
        current_size += len(line_bytes)
    return














def main():

    return


if __name__ == '__main__':
    main()